#ifndef U2ArchiveManager_H
#define U2ArchiveManager_H

#include "U2PreRequest.h"
#include "U2MemoryAllocatorConfig.h"
#include "U2SharedPtr.h"
#include "U2Singleton.h"
#include "U2ArchiveFactory.h"
#include "U2IteratorWrappers.h"


U2EG_NAMESPACE_BEGIN


class U2ArchiveManager : public U2Singleton<U2ArchiveManager>, public ArchiveAlloc
{
protected:
	typedef std::map<U2String, U2ArchiveFactory*> ArchiveFactoryMap;
	/// Factories available to create archives, indexed by archive type (String identifier e.g. 'Zip')
	ArchiveFactoryMap mArchFactories;
	/// Currently loaded archives
	typedef std::map<U2String, U2Archive*> ArchiveMap;
	ArchiveMap mArchives;

public:
	static U2ArchiveManager&		getSingleton(void);
	static U2ArchiveManager*		getSingletonPtr(void);
	
    U2ArchiveManager(void);
	virtual ~U2ArchiveManager(void);

    /** Opens an archive for file reading.
        @remarks
            The archives are created using class factories within
            extension libraries.
        @param filename
            The filename that will be opened
        @param refLibrary
            The library that contains the data-handling code
        @returns
            If the function succeeds, a valid pointer to an Archive
            object is returned.
        @par
            If the function fails, an exception is thrown.
    */
    U2Archive* load( const U2String& filename, const U2String& archiveType);

	/** Unloads an archive.
	@remarks
		You must ensure that this archive is not being used before removing it.
	*/
	void unload(U2Archive* arch);
	/** Unloads an archive by name.
	@remarks
		You must ensure that this archive is not being used before removing it.
	*/
	void unload(const U2String& filename);
	typedef MapIterator<ArchiveMap> ArchiveMapIterator;
	/** Get an iterator over the Archives in this Manager. */
	ArchiveMapIterator getArchiveIterator(void);

    /** Adds a new ArchiveFactory to the list of available factories.
        @remarks
            Plugin developers who add new archive codecs need to call
            this after defining their ArchiveFactory subclass and
            Archive subclasses for their archive type.
    */
    void addArchiveFactory(U2ArchiveFactory* factory);

};


U2EG_NAMESPACE_END

#endif